home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 09 - 1993 / 09.09 Sep 93 / FrameAnim App ƒ / Animation.c next >
Encoding:
Text File  |  1994-11-06  |  9.9 KB  |  361 lines  |  [TEXT/KAHL]

  1. // ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  2. // • Program:    FrameAnim
  3. // • File:        Animation.c
  4. // • 
  5. // • Copyright © 1993 by Scott B. Steinman, O.D., Ph.D. All Rights Reserved.
  6. // ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  7.  
  8. #include "FrameAnim.h"
  9.  
  10. // • ------------------ External Globals ---------------------------------- 
  11.  
  12. extern CWindowPtr        gMainWindow;    // • From Main.c file
  13. extern GWorldPtr        gFrames[];        // • From Main.c file
  14. extern PicHandle        gFramePICTs[];    // • From Files.c file
  15. extern PaletteHandle    gPalette;        // • From Main.c file
  16. extern CTabHandle        gCTable;        // • From Main.c file
  17. extern Settings            gSettings;        // • From Main.c file
  18. extern XVBLTask            gXVBLTask;        // • From VBlanks.c file                
  19.  
  20. // • ------------------ Globals ------------------------------------------- 
  21.  
  22. Rect                    gGlobBounds,    // • GWorld bounds in global coords 
  23.                         gBounds;        // • GWorld bounds in local coords
  24.  
  25. // •------------------- Static Variables ----------------------------------
  26.  
  27. static Rect                sDrawArea,         // • Regions in which to draw frames 
  28.                         sTarget;        // • Target square to be displayed 
  29. static Point            sOrigin,        // • Origin of display window 
  30.                         sCenter;        // • Center of GWorld 
  31. static short            sRectSize;        // • Length of target square side 
  32. static Boolean            sIncrSize;        // • True=grow, false=shrink target 
  33.  
  34. // • ------------------ Static Functions ---------------------------------- 
  35.  
  36. static void        PlaceTargets( const short );
  37. static void        SetDrawCoords( void );
  38.  
  39. // • ------------------ Find Drawing Origin ------------------------------- 
  40.  
  41. void
  42. FindOrigin( void )
  43. // •
  44. // • Find mathematical origin of the drawing window.                                
  45. {
  46.     short        v, h;    // • Size of drawing window (height, width) 
  47.             
  48.     h = gMainWindow->portRect.right - gMainWindow->portRect.left;
  49.     v = gMainWindow->portRect.bottom - gMainWindow->portRect.top;
  50.     SetPt( &sOrigin, h / 2, v / 2 );
  51. }
  52.  
  53. // • ------------------ Set Drawing Coordinates --------------------------- 
  54.  
  55. static void
  56. SetDrawCoords( void )
  57. // •
  58. // • Set up drawing bounds for GWorlds and display window
  59. // • in local and global coordinates.
  60. {
  61.     short        radius;
  62.     Point        topLeft, botRight;
  63.  
  64.     radius = gSettings.frameSize / 2;    // • Half-width of frame    
  65.     
  66.      // • Set up drawing area in GWorlds and center point of GWorlds 
  67.      
  68.     SetRect( &gBounds, 0, 0, gSettings.frameSize, gSettings.frameSize );
  69.     SetPt( &sCenter, gSettings.frameSize / 2, gSettings.frameSize / 2 );
  70.  
  71.     // • Set local coordinates in window for GWorld copying
  72.  
  73.     SetRect( &sDrawArea, sOrigin.h - radius, sOrigin.v - radius, 
  74.      sOrigin.h + radius, sOrigin.v + radius );
  75.  
  76.     // • Convert GWorld drawing area to global screen coordinates 
  77.     // • (Used in NewGWorld for faster CopyBits operations).
  78.     
  79.     SetPt( &topLeft, sDrawArea.left, sDrawArea.top );
  80.     LocalToGlobal( &topLeft );
  81.     SetPt( &botRight, sDrawArea.right, sDrawArea.bottom );
  82.     LocalToGlobal( &botRight );
  83.     SetRect( &gGlobBounds, topLeft.h, topLeft.v, botRight.h, botRight.v );        
  84. }
  85.  
  86. // • ------------------ Allocate Memory for Animation Frames -------------- 
  87.  
  88. void
  89. PrepareFilm( void )
  90. // •
  91. // • Initializes blocks of memory for the GWorlds to be stored.
  92. {
  93.     GDHandle        currentDev = NullHandle;
  94.     CGrafPtr        currentPort = NullPointer;
  95.     QDErr            qderror;
  96.     short            i;
  97.     Str255            errStr;
  98.     
  99.     GetGWorld( ¤tPort, ¤tDev );    // • Save current port & device  
  100.     UpdateWindowColors();                    // • Ensure palette is current    
  101.  
  102.     // • Free any previously-allocated animation frame GWorlds. 
  103.     
  104.     DisposeFrames();
  105.     
  106.     // • Set bounds for drawing into GWorlds and window.
  107.     
  108.     SetDrawCoords();
  109.  
  110.     // • Allocate space on heap for new GWorlds. 
  111.     
  112.     qderror = NewGWorld( &gFrames[ 0 ], 0, &gGlobBounds, NullHandle, 
  113.      NullHandle, (GWorldFlags) NoFlags );    
  114.     if (qderror != noErr) {
  115.         ErrNumToPstr( qderror, (char *) errStr );
  116.         ErrorHandler( kNoGWorldMsg, (char *) "\pErrorCode = ", 
  117.          (char *) errStr, (char *) NilString );
  118.     }
  119.     if (gFrames[ 0 ] == NullPointer)
  120.         ErrorHandler( kNoMemoryMsg, (char *) NilString, 
  121.          (char *) NilString, (char *) NilString );
  122.          
  123.     // • Move GWorld PixMaps to top of heap to maximize contiguous memory.
  124.      
  125.     MoveHHi( (Handle) GetGWorldPixMap( gFrames[ 0 ] ) );
  126.     
  127.     // • Prevent freeing of PixMap memory until we're ready.
  128.     
  129.     NoPurgePixels( GetGWorldPixMap( gFrames[ 0 ] ) );
  130.  
  131.     // • Get as much contiguous heap space for the GWorlds as possible.
  132.     
  133.     MaximizeHeap( (GetPtrSize( gFrames[ 0 ] ) + 
  134.      GetHandleSize( GetGWorldPixMap( gFrames[ 0 ] ) )) * kMaxFrames );
  135.     
  136.      for (i = 1; i < gSettings.numFrames; i++) {     
  137.         qderror = NewGWorld( &gFrames[ i ], 0, &gGlobBounds, NullHandle, 
  138.          GetGWorldDevice( gFrames[ 0 ] ), noNewDevice );    
  139.         if (qderror != noErr) {
  140.             ErrNumToPstr( qderror, (char *) errStr );
  141.             ErrorHandler( kNoGWorldMsg, (char *) "\pErrorCode = ", 
  142.              (char *) errStr, (char *) NilString );
  143.         }
  144.         if (gFrames[ i ] == NullPointer)
  145.             ErrorHandler( kNoMemoryMsg, (char *) NilString, 
  146.              (char *) NilString, (char *) NilString );
  147.         MoveHHi( (Handle) GetGWorldPixMap( gFrames[ i ] ) );
  148.         NoPurgePixels( GetGWorldPixMap( gFrames[ i ] ) );
  149.     }
  150.     
  151.     SetGWorld( currentPort, currentDev );    // • Restore port & device 
  152.     UpdateGWorldColors();
  153. }
  154.  
  155. // • ------------------ Plot Targets in Frames ---------------------------- 
  156.  
  157. static void
  158. PlaceTargets( const short frm )
  159. // • 
  160. // • Draws rectangle target inside frame for demonstrating animation.
  161. {
  162.     RGBColor    rgbTarget, rgbBkgnd;
  163.  
  164.     if (sIncrSize) {
  165.         sRectSize += gSettings.sizeDiff;    
  166.         if (sRectSize >= gSettings.frameSize - 10) {
  167.             sRectSize -= gSettings.sizeDiff * 2;
  168.             sIncrSize = false;
  169.         }
  170.     }
  171.     else {
  172.         sRectSize -= gSettings.sizeDiff;    
  173.         if (sRectSize <= 0) {
  174.             sRectSize += gSettings.sizeDiff * 2;
  175.             sIncrSize = true;
  176.         }
  177.     }
  178.     SetRect( &sTarget, sCenter.h - (sRectSize / 2), 
  179.      sCenter.v - (sRectSize / 2), sCenter.h + (sRectSize / 2), 
  180.      sCenter.v + (sRectSize / 2) );
  181.     
  182.     // • Draw target in offscreen GWorld
  183.  
  184.     PenSize( 2, 2 );    // • Set outline width for target rectangle.
  185.  
  186.     PmForeColor( kPalBkgnd );    // • Clear background 
  187.     PaintRect( &gBounds );
  188.  
  189.     PmForeColor( kPalTarget );    // • Draw rectangle outline
  190.     FrameRect( &sTarget );        
  191.  
  192.     ResetForeAndBackColors();
  193.     
  194.     // • Get background and target colors
  195.     
  196.     GetEntryColor( gPalette, kPalBkgnd, &rgbBkgnd );
  197.     GetEntryColor( gPalette, kPalTarget, &rgbTarget );
  198.     
  199.     // • Repeat drawing into PICT for saving to file.
  200.     // • Use Color Mgr routines instead of Palette Mgr!
  201.     
  202.     gFramePICTs[ frm ] = OpenPicture( &gBounds );
  203.     
  204.     PenSize( 2, 2 );
  205.     RGBForeColor( &rgbBkgnd );
  206.     PaintRect( &gBounds );
  207.     RGBForeColor( &rgbTarget );
  208.     FrameRect( &sTarget );        
  209.  
  210.     ClosePicture();
  211.     
  212.     ResetForeAndBackColors();
  213. }
  214.  
  215. // • ------------------ Record the Frames into a Film Sequence ------------ 
  216.  
  217. void
  218. DoFilm( void )
  219. // •
  220. // • Records the frames which are later shown with PlayFilm.
  221. {
  222.     GDHandle    currentDev = NullHandle;
  223.     CGrafPtr    currentPort = NullPointer;
  224.     short        i;                    
  225.     
  226.  
  227.     sRectSize = 0;        
  228.     sIncrSize = true;
  229.  
  230.     PrepareFilm();                        // • Allocate film storage. 
  231.     
  232.     GetGWorld( ¤tPort, ¤tDev );    // • Save current port & device      
  233.     for (i = 0; i < gSettings.numFrames; i++) {
  234.         
  235.         // • Draw frame area directly into GWorld 
  236.         
  237.         LockPixels( GetGWorldPixMap( gFrames[ i ] ) );                    
  238.         SetGWorld( gFrames[ i ], NullPointer );
  239.         PlaceTargets( i );                        
  240.         SetGWorld( currentPort, currentDev );    // • Reset port & device  
  241.         UnlockPixels( GetGWorldPixMap( gFrames[ i ] ) );                    
  242.         ResetForeAndBackColors();
  243.     }
  244.     SysBeep( 1 );
  245. }
  246.  
  247. // • ------------------ Show Recorded Animation Sequence ------------------ 
  248.  
  249. void
  250. PlayFilm( void )
  251. // •
  252. // • Play a pre-recorded animation sequence.
  253. {
  254.     long        finalTicks;
  255.     short        i;
  256.  
  257.     ResetForeAndBackColors();
  258.     HideCursor();                // • Get cursor out of the way 
  259.  
  260.     for (i = 0; i < gSettings.numFrames; i++)
  261.         LockPixels( GetGWorldPixMap( gFrames[ i ] ) ); 
  262.  
  263.     // • Insert our VBlank task into interrupt queue. 
  264.  
  265.     SetUpVBlankAnimation();
  266.     
  267.     // • Allow VBlank task to execute.
  268.     
  269.     gXVBLTask.vbl.vblCount = 1;        
  270.  
  271.     // • Once per VBlank, copy a frame to the screen.
  272.  
  273.     while (gXVBLTask.frameIndex < gSettings.numFrames) {
  274.          if (gXVBLTask.showFrame == true) {
  275.             gXVBLTask.showFrame = false;
  276.             CopyBits( &gFrames[ gXVBLTask.frameIndex ]->portPixMap, 
  277.              &gMainWindow->portPixMap, &gBounds, &sDrawArea, srcCopy, 
  278.              NullHandle );
  279.         }
  280.     }
  281.     
  282.     // • Remove VBlank task from interrupt queue. 
  283.     
  284.     ShutDownVBlankAnimation();
  285.         
  286.     for (i = 0; i < gSettings.numFrames; i++)
  287.         UnlockPixels( GetGWorldPixMap( gFrames[ i ] ) ); 
  288.  
  289.     // • Clear the screen when finished. 
  290.  
  291.     Delay( 5, &finalTicks );
  292.     PmForeColor( kPalBkgnd );     
  293.     PaintRect( &(gMainWindow->portRect) );    // • Clear window background
  294.     ResetForeAndBackColors();
  295.     ShowCursor();                            // • Put the cursor back out 
  296. }
  297.  
  298. // • ------------------ Update Frame GWorld Palettes ---------------------- 
  299.  
  300. void
  301. UpdateGWorldColors( void )
  302. // •
  303. // • Sets gray levels of GWorlds.
  304. {
  305.     GDHandle        currentDev = NullHandle;
  306.     CGrafPtr        currentPort = NullPointer;
  307.     short            i;
  308.  
  309.     GetGWorld( ¤tPort, ¤tDev );        // • Save current port & device  
  310.      for (i = 0; i < gSettings.numFrames; i++) {    
  311.         if (gFrames[ i ] != NullPointer) {
  312.             SetGWorld( gFrames[ i ], NullPointer );
  313.             NSetPalette( (WindowPtr) gFrames[ i ], gPalette, true );
  314.             ActivatePalette( (WindowPtr) gFrames[ i ] );
  315.         }         
  316.     }                    
  317.     SetGWorld( currentPort, currentDev );        // • Restore port & device 
  318. }
  319.  
  320. // • ------------------ Dispose of the Frame GWorlds ---------------------- 
  321.     
  322. void
  323. DisposeFrames( void )
  324. // •
  325. // • Dispose of the animation frame GWorlds.
  326. {
  327.     short        i;
  328.     
  329.      for (i = 0; i < kMaxFrames; i++) {
  330.          if (gFrames[ i ] != NullPointer) {
  331.              DisposeGWorld( gFrames[ i ] );
  332.             gFrames[ i ] = NullPointer;
  333.         }
  334.     }
  335. }
  336.  
  337. // • ------------------ Reset Foreground & Background Colors -------------- 
  338.  
  339. void
  340. ResetForeAndBackColors( void )
  341. {
  342.     PmForeColor( kPalBlack );
  343.     PmBackColor( kPalWhite );
  344. }
  345.  
  346. // • ------------------ Round Up a Number --------------------------------- 
  347.  
  348. short
  349. RoundUp( const double inputNumber )
  350. // •
  351. // • Rounds up a floating-point number into next highest whole integer.
  352. {
  353.     short        wholeNumber, roundNumber;
  354.     
  355.     wholeNumber = (short) inputNumber;
  356.     if (inputNumber - wholeNumber == 0.0)    
  357.         return( wholeNumber );
  358.     else                                    
  359.         return( wholeNumber + 1 );
  360. }
  361.